using System;
using System.Collections.Generic;
using System.Windows.Forms;
using OhioState.AssetManaged;
using OhioState.Graphics;
using OhioState.Graphics.Proxy;
using OhioState.Math;

namespace ShapeEditor
{
    public partial class RegionOfInterestControl : UserControl
    {
        //For now assume box..
        private ROIBoxProxy roi;
        private ShapeType shapeType;
        private AssetManager assetMan;

        private delegate void ROIHandler(ROIBoxProxy ROI);

        public RegionOfInterestControl()
        {
            InitializeComponent();
            assetMan = AssetManager.Instance;
            shapeType = ShapeType.Box;
            this.slicingDirCombo.SelectedIndex = 0;
            assetManagerDropDownControl1.Init(typeof(IShape));
            assetManagerDropDownControl1.SelectedEvent += new IAssetManagedHandler(assetManagerDropDownControl1_SelectedEvent);
        }

        #region Public properties

        //
        // Public properties
        //
        public ROIBoxProxy ROI
        {
            get { return roi; }
        }

        
        //
        // Set the focus of this control to a new ROI.  Be careful of thread issues
        private void SetROI_thisThread(ROIBoxProxy ROI)
        {
            roi = null;
            //
            // Toggle Enabled based on whether the ROI is null or not
            //
            if (ROI == null)
            {
                this.Enabled = false;
            }
            else
            {
                this.Enabled = true;

                //
                // Populate control with ROI values
                //
                sliceUpDown.Value = new Decimal(ROI.SliceThickness);
                // Size
                //BoundingBox bBox = ROI.BoundingVolume as BoundingBox;
                SharedBox box = ROI.Box;
                assetManagerDropDownControl1.SelectItem(box);
            }
            roi = ROI;
        }
        //
        // Force the event to get called on the proper thread.  The DataGridView complains if you try
        //  to use it on the wrong thread.
        //
        public void SetROI(ROIBoxProxy ROI)
        {
            ROIHandler newEvent = new ROIHandler(SetROI_thisThread);
            object[] args = new object[1];
            args[0] = ROI;
            //
            // We need to make sure these methods are executed on the correct thread.
            //
            try
            {
                if (this.InvokeRequired)
                    this.Invoke(newEvent, args);
                else
                    newEvent(ROI);
            }
            catch { }
        }

        #endregion

        private void assetManagerDropDownControl1_SelectedEvent(IAssetManaged obj)
        {
            if (roi != null)
            {
                roi.Box = (SharedBox)obj;
            }
        }

        public IShape SelectDefault()
        {
            List<IShape> iShapes = new List<IShape>();
            // Hack for now only SharedBox
            List<IAssetManaged> list2 = assetMan.FindAll(typeof(SharedBox));
            foreach (IAssetManaged obj in list2)
            {
                if(obj is IShape)
                    iShapes.Add((IShape)obj);
            }
            if (iShapes.Count > 0)
            {
                assetManagerDropDownControl1.SelectItem((IAssetManaged)iShapes[0]);
                return iShapes[0];
            }

            return null;
        }

        private void sliceUpDown_ValueChanged(object sender, EventArgs e)
        {
            
            if (roi != null)
            {
                roi.SliceThickness = Decimal.ToSingle(sliceUpDown.Value);
            }

        }

        private void directionThetaPhiUpDown_ValueChanged(object sender, EventArgs e)
        {
            Vector3 sliceDir = new Vector3();
            double theta = System.Math.PI * Decimal.ToDouble(this.directionThetaUpDown.Value) / 180.0;
            double phi = System.Math.PI * Decimal.ToDouble(this.directionPhiUpDown.Value) / 180.0;
            double cosTheta = System.Math.Cos(theta);
            double sinTheta = System.Math.Sin(theta);
            double cosPhi = System.Math.Cos(phi);
            double sinPhi = System.Math.Sin(phi);
            sliceDir[0] = (float)(cosTheta * sinPhi);
            sliceDir[1] = (float)(sinTheta * sinPhi);
            sliceDir[2] = (float)(cosPhi);
            if(roi != null)
                roi.SliceDirection = sliceDir;
        }

        private void slicingDirCombo_SelectedIndexChanged(object sender, EventArgs e)
        {
            //
            // if Fixed-direction, expose the direction Box
            //
            if (this.slicingDirCombo.SelectedIndex >= 2)
            {
                this.slicingDirGroupBox.Visible = true;
            }
            else
            {
                this.slicingDirGroupBox.Visible = false;
            }
            //
            // Set the ROI slicing direction.
            //
            if (roi != null)
            {
                switch (this.slicingDirCombo.SelectedIndex)
                {
                    case 0:
                        roi.SlicingMode = SliceDirection.SliceDirMode.VIEW_ALIGNED;
                        break;
                    case 1:
                        roi.SlicingMode = SliceDirection.SliceDirMode.WORLD_ALIGNED;
                        break;
                    case 2:
                        roi.SlicingMode = SliceDirection.SliceDirMode.FIXED_VIEW_DIR;
                        break;
                    case 3:
                        roi.SlicingMode = SliceDirection.SliceDirMode.FIXED_WORLD_DIR;
                        break;
                }
            }
        }

        public ShapeType ShapeType
        {
            get { return shapeType; }
            set { shapeType = value; }
        }
        public delegate void ROIVisibility(bool isVisible);

        public void Visibility(bool isVisible)
        {
            ROIVisibility roiVisibility = new ROIVisibility(IsVisible_ThisThread);

            object[] args = new object[1];
            args[0] = isVisible;
            //
            // We need to make sure these methods are executed on the correct thread.
            //
            try
            {
                if (this.InvokeRequired)
                    this.Invoke(roiVisibility, args);
                else
                    roiVisibility(isVisible);
            }
            catch { }

        }

        public void IsVisible_ThisThread(bool isVisible)
        {
            this.Visible = isVisible;
        }
    }
}
